﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MvCameraControl;
using System.Threading;
using System.IO;
using System.Reflection.Emit;
using System.Drawing.Imaging;
using csLTDMC;
using InspectionMAC.Function;
using InspectionMAC.Forms;
using InspectionMAC.Algorithm;
using System.Collections.Concurrent;

namespace InspectionMAC.SystemThread
{
    class CameraReceiveThread_03
    {
        static readonly DeviceTLayerType enumTLayerType = DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvUsbDevice
| DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvGenTLCXPDevice | DeviceTLayerType.MvGenTLCameraLinkDevice | DeviceTLayerType.MvGenTLXoFDevice;

        static List<IDeviceInfo> deviceInfoList = new List<IDeviceInfo>();
        public static IDevice device = null;

        public static bool isGrabbing = false;        // ch:是否正在取图 | en: Grabbing flag
        static Thread receiveThread = null;    // ch:接收图像线程 | en: Receive image thread

        public static IFrameOut frameForSave;                         // ch:获取到的帧信息, 用于保存图像 | en:Frame for save image
        public static readonly object saveImageLock = new object();

        public static void CameraInitialize()
        {
            SDKSystem.Initialize();

            RefreshDeviceList();

            Control.CheckForIllegalCrossThreadCalls = false;

            OpenDevice();//打开相机




            //ContinuousMotion();//连续运动
        }

        // ch:显示错误信息 | en:Show error message
        public static void ShowErrorMsg(string message, int errorCode)
        {
            string errorMsg;
            if (errorCode == 0)
            {
                errorMsg = message;
            }
            else
            {
                errorMsg = message + ": Error =" + String.Format("{0:X}", errorCode);
            }

            switch (errorCode)
            {
                case MvError.MV_E_HANDLE: errorMsg += " Error or invalid handle "; break;
                case MvError.MV_E_SUPPORT: errorMsg += " Not supported function "; break;
                case MvError.MV_E_BUFOVER: errorMsg += " Cache is full "; break;
                case MvError.MV_E_CALLORDER: errorMsg += " Function calling order error "; break;
                case MvError.MV_E_PARAMETER: errorMsg += " Incorrect parameter "; break;
                case MvError.MV_E_RESOURCE: errorMsg += " Applying resource failed "; break;
                case MvError.MV_E_NODATA: errorMsg += " No data "; break;
                case MvError.MV_E_PRECONDITION: errorMsg += " Precondition error, or running environment changed "; break;
                case MvError.MV_E_VERSION: errorMsg += " Version mismatches "; break;
                case MvError.MV_E_NOENOUGH_BUF: errorMsg += " Insufficient memory "; break;
                case MvError.MV_E_UNKNOW: errorMsg += " Unknown error "; break;
                case MvError.MV_E_GC_GENERIC: errorMsg += " General error "; break;
                case MvError.MV_E_GC_ACCESS: errorMsg += " Node accessing condition error "; break;
                case MvError.MV_E_ACCESS_DENIED: errorMsg += " No permission "; break;
                case MvError.MV_E_BUSY: errorMsg += " Device is busy, or network disconnected "; break;
                case MvError.MV_E_NETER: errorMsg += " Network error "; break;
            }

            MessageBox.Show(errorMsg, "PROMPT");
        }

        public static bool SwitchUserSet(uint userSetNumber)
        {
            if (device == null)
            {
                MessageBox.Show("相机3未连接");
                return false;
            }
            StopGrab();


            try
            {
                int nRet = device.Parameters.SetEnumValue("UserSetSelector", userSetNumber);
                if (nRet != MvError.MV_OK)
                {
                    ShowErrorMsg("相机3用户集设置失败", nRet);
                    return false;
                }
                nRet = device.Parameters.SetCommandValue("UserSetLoad");
                if (nRet != 0)
                {
                    MessageBox.Show($"相机3加载用户集失败，错误代码: {nRet}");
                    return false;
                }
                nRet = device.Parameters.SetEnumValue("UserSetDefault", userSetNumber);
                if (nRet != MvError.MV_OK)
                {
                    ShowErrorMsg("相机3默认用户集设置失败", nRet);
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"相机3切换用户集时发生错误: {ex.Message}");
                return false;
            }
            StartGrab();
        }
        //刷新设备列表
        private static void RefreshDeviceList()
        {
            // ch:创建设备列表 | en:Create Device List

            int nRet = DeviceEnumerator.EnumDevices(enumTLayerType, out deviceInfoList);
            if (nRet != MvError.MV_OK)
            {
                //ShowErrorMsg("Enumerate devices fail!", nRet);
                return;
            }


        }

        public static void OpenDevice()
        {
            if (ImageQueue != null)
            {
                while (ImageQueue.TryTake(out IFrameOut frame))
                {
                    frame?.Dispose();
                }
            }
            else
            {
                ImageQueue = new BlockingCollection<IFrameOut>(10);
            }
            // 记录枚举到的设备数量
            MacTestForm.macTestForm.AddLog($"枚举到 {deviceInfoList.Count} 个设备");

            //判断有无设备
            if (deviceInfoList.Count == 0)
            {
                MacTestForm.macTestForm.AddLog("警告：未找到任何相机设备");
                return;
            }

            // 查找特定序列号的相机
            IDeviceInfo deviceInfo = null;
            string targetSerial = MacTestForm.macTestForm.appConfig.AppSettings.Cameras[2].CameraId;
            for (int i = 0; i < deviceInfoList.Count; i++)
            {
                if (deviceInfoList[i].SerialNumber == targetSerial)
                {
                    deviceInfo = deviceInfoList[i];
                    break;
                }
            }

            if (deviceInfo == null)
            {
                MacTestForm.macTestForm.AddLog($"错误：未找到序列号为 {targetSerial} 的相机");
                return;
            }

            MacTestForm.macTestForm.AddLog($"找到相机3，序列号：{deviceInfo.SerialNumber}");

            try
            {
                // 打开设备
                device = DeviceFactory.CreateDevice(deviceInfo);
                MacTestForm.macTestForm.AddLog("相机3 - 创建设备实例成功");
            }
            catch (Exception ex)
            {
                MacTestForm.macTestForm.AddLog($"相机3 - 创建设备实例失败: {ex.Message}");
                return;
            }

            int result = device.Open();
            if (result != MvError.MV_OK)
            {
                MacTestForm.macTestForm.AddLog($"相机3 - 打开设备失败，错误代码: {result}");

                return;
            }
            else
            {
                MacTestForm.macTestForm.AddLog("相机3 - 打开设备成功");
            }

            //ch: 判断是否为gige设备 | en: Determine whether it is a GigE device
            if (device is IGigEDevice)
            {
                //ch: 转换为gigE设备 | en: Convert to Gige device
                IGigEDevice gigEDevice = device as IGigEDevice;

                // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                int optionPacketSize;
                result = gigEDevice.GetOptimalPacketSize(out optionPacketSize);
                if (result != MvError.MV_OK)
                {
                    MacTestForm.macTestForm.AddLog("相机3 - 警告：获取最佳包大小失败");
                }
                else
                {
                    result = device.Parameters.SetIntValue("GevSCPSPacketSize", (long)optionPacketSize);
                    if (result != MvError.MV_OK)
                    {
                        MacTestForm.macTestForm.AddLog("相机3 - 警告：设置包大小失败");
                    }
                }
            }
            
            // 设置触发模式
            result = device.Parameters.SetEnumValueByString("TriggerMode", "On");
            if (result != MvError.MV_OK)
            {
                MacTestForm.macTestForm.AddLog("相机3 - 警告：设置触发模式失败");
            }

            result = device.Parameters.SetEnumValueByString("TriggerSource", "Line0");
            if (result != MvError.MV_OK)
            {
                MacTestForm.macTestForm.AddLog("相机3 - 警告：设置触发源失败");
            }
            else
            {
                MacTestForm.macTestForm.AddLog("相机3 - 触发模式设置成功：硬件触发(Line0)");
            }

            StartGrab();//开始抓图
        }
        public static void StartGrab()
        {

            // 开始采集（进入待触发状态）
            int result = device.StreamGrabber.StartGrabbing();
            if (result != MvError.MV_OK)
            {
                ShowErrorMsg("启动采集失败！", result);
                return;
            }

            isGrabbing = true;  // 标志位，表示相机在等待触发
            receiveThread = new Thread(ReceiveThreadProcess);
            receiveThread.Start();  // 启动线程，等待图像数据s
            //try
            //{
            //    // ch:标志位置位true | en:Set position bit true
            //    isGrabbing = true;

            //    receiveThread = new Thread(ReceiveThreadProcess);
            //    receiveThread.Start();
            //   // MessageBox.Show("抓取线程开启");
            //}
            //catch (Exception ex)
            //{
            //    MessageBox.Show("Start thread failed!, " + ex.Message);
            //    throw;
            //}

            // ch:开始采集 | en:Start Grabbing
            //int result = device.StreamGrabber.StartGrabbing();
            //MessageBox.Show("开始抓取");
            //if (result != MvError.MV_OK)
            //{
            //    isGrabbing = false;
            //    receiveThread.Join();
            //    //ShowErrorMsg("Start Grabbing Fail!", result);
            //    return;
            //}


        }
        public static void StopGrab()
        {
            isGrabbing = false;

            // 设置合理超时时间，避免永久阻塞
            if (receiveThread != null && receiveThread.IsAlive)
            {
                if (!receiveThread.Join(1500)) // 1.5秒超时
                {
                    receiveThread.Interrupt(); // 安全中断
                }
            }

            // ch:停止采集 | en:Stop Grabbing
            int result = device.StreamGrabber.StopGrabbing();
            if (result != MvError.MV_OK)
            {
                //ShowErrorMsg("Stop Grabbing Fail!", result);
            }
        }

        public static void CloseDevice()
        {
            // ch:取流标志位清零 | en:Reset flow flag bit
            if (isGrabbing == true)
            {
                StopGrab();
            }

            while (ImageQueue.TryTake(out IFrameOut frame))
            {
                frame?.Dispose();
            }
            //ImageQueue.CompleteAdding();
            // ch:关闭设备 | en:Close Device
            if (device != null)
            {
                device.Close();
                device.Dispose();
            }
            lock (saveImageLock)
            {
                if (frameForSave != null)
                {
                    frameForSave.Dispose();
                    frameForSave = null;
                }
            }

            SDKSystem.Finalize();
            // ch:控件操作 | en:Control Operation
            //SetCtrlWhenClose();
            //StopTriggerLoop();
        }

        public void SoftTriggerCamera()
        {

        }
        public static bool isImageData;
        public static bool isImageData1;
        public static DateTime imageDateTime;

        public static Image image;
        // 在每个相机线程类中添加
        public static BlockingCollection<IFrameOut> ImageQueue = new BlockingCollection<IFrameOut>(10); // 缓冲10张图像
        private static DateTime _lastImageTime = DateTime.MinValue;
        private static readonly object _timeLock = new object();
        private const int MIN_IMAGE_INTERVAL_MS = 50;

        /// <summary>
        /// 检查图像时间间隔是否有效（≥50ms）
        /// </summary>
        private static bool CheckImageInterval()
        {
            lock (_timeLock)
            {
                TimeSpan interval = DateTime.Now - _lastImageTime;
                return interval.TotalMilliseconds >= MIN_IMAGE_INTERVAL_MS;
            }
        }

        /// <summary>
        /// 更新最后图像时间戳
        /// </summary>
        private static void UpdateLastImageTime()
        {
            lock (_timeLock)
            {
                _lastImageTime = DateTime.Now;
            }
        }
        public static void ReceiveThreadProcess()
        {
            int nRet;
            Console.WriteLine("相机3图像接收线程启动");

            while (isGrabbing)
            {
                IFrameOut frameOut;
                nRet = device.StreamGrabber.GetImageBuffer(100, out frameOut);

                if (MvError.MV_OK == nRet)
                {
                    // 检查时间间隔
                    bool isValidImage = CheckImageInterval();
                    if (!isValidImage)
                    {
                        Console.WriteLine($"相机3图像间隔过短，丢弃图像: {DateTime.Now:HH:mm:ss.fff}");
                        device.StreamGrabber.FreeImageBuffer(frameOut);
                        Thread.Sleep(1); // 短暂休眠
                        continue;
                    }
                    Console.WriteLine($"相机3取到有效图像: { DateTime.Now:HH: mm: ss.fff}");
                    try
                    {
                        // 检查队列容量，防止内存溢出
                        if (ImageQueue.Count < 10)
                        {
                            var clonedFrame = frameOut.Clone() as IFrameOut;

                            if (ImageQueue.TryAdd(clonedFrame, 50)) // 50ms超时
                            {
                                Console.WriteLine($"相机3图像入队成功: {DateTime.Now:HH:mm:ss.fff} 队列深度: {ImageQueue.Count}/10");
                                UpdateLastImageTime();

                                if (MacTestForm.macTestForm.isPointSet && PointSetForm.DisplayQueue01 != null)
                                {
                                    try
                                    {
                                        Bitmap displayBitmap = clonedFrame.Image.ToBitmap();
                                        Bitmap clonedBitmap = (Bitmap)displayBitmap.Clone();
                                        PointSetForm.DisplayQueue03.Enqueue(clonedBitmap);
                                    }
                                    catch (Exception ex)
                                    {
                                        Console.WriteLine($"实时显示异常: {ex.Message}");
                                    }
                                }
                                if (!MacTestForm.macTestForm.isStart&&!MacTestForm.macTestForm.isPointSet)
                                {

                                    Bitmap image = clonedFrame.Image.ToBitmap();
                                    //保存图片
                                    string dateFolder = imageDateTime.ToString("yyyyMMdd");
                                    string hourFolder = imageDateTime.ToString("HH");
                                    string relativePath = Path.Combine(@"Image", dateFolder, hourFolder, "Single3");
                                    string fileName = $"{imageDateTime:yyyyMMdd_HHmmssfff}.jpg";
                                    string fullPath = Path.Combine(Application.StartupPath, relativePath);
                                    // 确保目录存在
                                    if (!Directory.Exists(fullPath))
                                    {
                                        Directory.CreateDirectory(fullPath);
                                    }
                                    string filePath = Path.Combine(fullPath, fileName);
                                    if (clonedFrame.Image != null)
                                    {
                                        image.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);
                                    }
                                    AlgorithmModule.ImageHandleBitmap2(image, 3);
                                }
                            }
                            else
                            {
                                Console.WriteLine("警告：相机3图像入队超时，丢弃图像");
                                clonedFrame?.Dispose();
                            }
                        }
                        else
                        {
                            Console.WriteLine("警告：相机3图像队列已满，丢弃图像");
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"相机3图像处理异常: {ex.Message}");
                    }

                    device.StreamGrabber.FreeImageBuffer(frameOut);
                }
                else
                {
                    Thread.Sleep(1); // 短暂休眠避免CPU占用过高
                }
            }

            //Console.WriteLine("相机3图像接收线程结束");
        }

        private static void GetParam()
        {
            IFloatValue floatValue;
            int result = device.Parameters.GetFloatValue("ExposureTime", out floatValue);
            if (result == MvError.MV_OK)
            {
                //tbExposure.Text = floatValue.CurValue.ToString("F1");
            }

            result = device.Parameters.GetFloatValue("Gain", out floatValue);
            if (result == MvError.MV_OK)
            {
                //tbGain.Text = floatValue.CurValue.ToString("F1");
            }

            result = device.Parameters.GetFloatValue("ResultingFrameRate", out floatValue);
            if (result == MvError.MV_OK)
            {
                //tbFrameRate.Text = floatValue.CurValue.ToString("F1");
            }

            //cbPixelFormat.Items.Clear();
            IEnumValue enumValue;
            result = device.Parameters.GetEnumValue("PixelFormat", out enumValue);
            if (result == MvError.MV_OK)
            {
                foreach (var item in enumValue.SupportEnumEntries)
                {
                    //cbPixelFormat.Items.Add(item.Symbolic);
                    if (item.Symbolic == enumValue.CurEnumEntry.Symbolic)
                    {
                        //cbPixelFormat.SelectedIndex = cbPixelFormat.Items.Count - 1;
                    }
                }

            }
        }
        /// <summary>
        /// ch:获取触发模式 | en:Get Trigger Mode
        /// </summary>
        private void GetTriggerMode()
        {
            IEnumValue enumValue;
            int result = device.Parameters.GetEnumValue("TriggerMode", out enumValue);
            if (result == MvError.MV_OK)
            {
                if (enumValue.CurEnumEntry.Symbolic == "On")
                {
                    //bnTriggerMode.Checked = true;
                    //bnContinuesMode.Checked = false;

                    result = device.Parameters.GetEnumValue("TriggerSource", out enumValue);
                    if (result == MvError.MV_OK)
                    {
                        if (enumValue.CurEnumEntry.Symbolic == "TriggerSoftware")
                        {
                            //cbSoftTrigger.Enabled = true;
                            //cbSoftTrigger.Checked = true;
                            //if (isGrabbing)
                            //{
                            //    bnTriggerExec.Enabled = true;
                            //}
                        }
                    }
                }
                else
                {
                    //bnContinuesMode.Checked = true;
                    //bnTriggerMode.Checked = false;
                }
            }
        }


        //开始抓取触发流程
        private static void StartGrabTrigger()
        {


            MessageBox.Show("触发准备完成");
        }
        //停止抓取流程
        public static void StopGrabTrigger()
        {

        }
        //伺服始能
        private static void ServoStart()
        {
            if (LTDMC.dmc_read_sevon_pin(DMC300_Info.usCardId[0], 0) == 1)      //當讀取狀態為1時，當下始能未開啟
            {
                LTDMC.dmc_write_sevon_pin(DMC300_Info.usCardId[0], 0, 0);       //下達0時是開啟始能
            }
            else
            {
                LTDMC.dmc_write_sevon_pin(DMC300_Info.usCardId[0], 0, 1);       ////下達1時是關閉始能
            }
        }
        //正向连续运动
        public static void ContinuousMotion()
        {
            ushort usAxis = 0; //轴号
            double dStartVel = 100;           //起始速度
            double dMaxVel = 10000;             //运行速度
            double dTacc = 0.5;               //加速时间
            double dTdec = 0.5;               //减速时间
            double dStopVel = 100;            //停止速度
            double dSpara = 0.2;              //S段时间       
            ushort usDir = 1;               //运动方向

            LTDMC.dmc_set_profile(DMC300_Info.usCardId[0], usAxis, dStartVel, dMaxVel, dTacc, dTdec, dStopVel);//设置速度参数
            LTDMC.dmc_set_s_profile(DMC300_Info.usCardId[0], usAxis, 0, dSpara);                                    //设置S段速度参数
            LTDMC.dmc_vmove(DMC300_Info.usCardId[0], usAxis, usDir);
        }
        //反向连续运动
        public static void BackContinuousMotion()
        {
            ushort usAxis = 0; //轴号
            double dStartVel = 100;           //起始速度
            double dMaxVel = 10000;             //运行速度
            double dTacc = 0.5;               //加速时间
            double dTdec = 0.5;               //减速时间
            double dStopVel = 100;            //停止速度
            double dSpara = 0.2;              //S段时间       
            ushort usDir = 0;               //运动方向

            LTDMC.dmc_set_profile(DMC300_Info.usCardId[0], usAxis, dStartVel, dMaxVel, dTacc, dTdec, dStopVel);//设置速度参数
            LTDMC.dmc_set_s_profile(DMC300_Info.usCardId[0], usAxis, 0, dSpara);                                    //设置S段速度参数
            LTDMC.dmc_vmove(DMC300_Info.usCardId[0], usAxis, usDir);
        }
        //停止运动
        public static void StopMotion()
        {
            ushort usAxis = 0;                             //轴号
            ushort usStopMode = 0;                                 //制动方式，0：减速停止，1：紧急停止
            double dTdec = Double.Parse("0.5");       //减速时间         
            LTDMC.dmc_set_dec_stop_time(DMC300_Info.usCardId[0], usAxis, dTdec);  //设置减速停止时间
            LTDMC.dmc_stop(DMC300_Info.usCardId[0], usAxis, usStopMode);
        }


    }
}
